package com.hejia.alauda.service;

import static com.hejia.alauda.utils.Utils.getExternal;
import static java.lang.Integer.MAX_VALUE;
import static java.util.concurrent.TimeUnit.SECONDS;
import static org.apache.commons.lang3.StringUtils.trimToEmpty;
import static org.apache.commons.lang3.time.DateFormatUtils.ISO_DATE_FORMAT;
import static org.apache.commons.lang3.time.DateUtils.addDays;
import static org.springframework.util.CollectionUtils.isEmpty;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.concurrent.Executor;

import javax.annotation.Resource;

import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.DateFormatUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.eclipse.jetty.util.StringUtil;
import org.springframework.core.task.AsyncTaskExecutor;
import org.springframework.dao.DataAccessException;
import org.springframework.data.redis.core.BoundValueOperations;
import org.springframework.data.redis.core.RedisOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.SessionCallback;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.hejia.alauda.entity.Account;
import com.hejia.alauda.entity.Balance;
import com.hejia.alauda.entity.BalanceOperation;
import com.hejia.alauda.entity.BankCard;
import com.hejia.alauda.entity.BonusRecord;
import com.hejia.alauda.entity.Channel;
import com.hejia.alauda.entity.Credit;
import com.hejia.alauda.entity.Feedback;
import com.hejia.alauda.entity.Financing;
import com.hejia.alauda.entity.Interest;
import com.hejia.alauda.entity.Invitation;
import com.hejia.alauda.entity.LoginHistory;
import com.hejia.alauda.entity.Popularize;
import com.hejia.alauda.entity.PopularizeCategory;
import com.hejia.alauda.entity.User;
import com.hejia.alauda.entity.UserInformation;
import com.hejia.alauda.entity.example.AccountExample;
import com.hejia.alauda.entity.example.BankCardExample;
import com.hejia.alauda.entity.example.ChannelExample;
import com.hejia.alauda.entity.example.Example.Criteria;
import com.hejia.alauda.entity.example.FinancingExample;
import com.hejia.alauda.entity.example.InterestExample;
import com.hejia.alauda.entity.example.InvitationExample;
import com.hejia.alauda.entity.example.OrderExample;
import com.hejia.alauda.entity.example.RepaymentOrderExample;
import com.hejia.alauda.entity.example.UserExample;
import com.hejia.alauda.entity.example.UserInformationExample;
import com.hejia.alauda.event.EventConstant;
import com.hejia.alauda.event.MessageEvent;
import com.hejia.alauda.exception.BusinessException;
import com.hejia.alauda.persistence.BaseMapper;
import com.hejia.alauda.persistence.mybatis.AccountMapper;
import com.hejia.alauda.persistence.mybatis.BalanceMapper;
import com.hejia.alauda.persistence.mybatis.BalanceOperationMapper;
import com.hejia.alauda.persistence.mybatis.BankCardMapper;
import com.hejia.alauda.persistence.mybatis.BonusRecordMapper;
import com.hejia.alauda.persistence.mybatis.ChannelMapper;
import com.hejia.alauda.persistence.mybatis.CreditMapper;
import com.hejia.alauda.persistence.mybatis.FeedbackMapper;
import com.hejia.alauda.persistence.mybatis.FinancingMapper;
import com.hejia.alauda.persistence.mybatis.InterestMapper;
import com.hejia.alauda.persistence.mybatis.InvitationMapper;
import com.hejia.alauda.persistence.mybatis.LoginHistoryMapper;
import com.hejia.alauda.persistence.mybatis.OrderMapper;
import com.hejia.alauda.persistence.mybatis.PopularizeCategoryMapper;
import com.hejia.alauda.persistence.mybatis.PopularizeMapper;
import com.hejia.alauda.persistence.mybatis.RepaymentOrderMapper;
import com.hejia.alauda.persistence.mybatis.UserInformationMapper;
import com.hejia.alauda.persistence.mybatis.UserMapper;
import com.hejia.alauda.utils.Encryption;
import com.hejia.alauda.utils.IdcardUtils;
import com.hejia.alauda.utils.Mobile;
import com.hejia.alauda.utils.Pager;
import com.hejia.alauda.utils.RateUtil;
import com.hejia.alauda.utils.RegionalUtil;
import com.hejia.hermes.entity.SMS;
import com.hejia.hermes.service.SMSService;

@Service
public class UserServiceImpl extends BaseServiceImpl<User> implements UserService {

	private final Log logger = LogFactory.getLog(getClass());
	@Resource
	private UserMapper userMapper;

	@Resource
	private BalanceMapper balanceMapper;

	@SuppressWarnings("rawtypes")
	@Resource
	private RedisTemplate redisTemplate;

	@Resource
	private UserInformationMapper userInformationMapper;

	@Resource
	private CreditMapper creditMapper;

	@Resource
	private FinancingMapper financingMapper;

	@Resource
	private InterestMapper interestMapper;

	@Resource
	private LoginHistoryMapper loginHistoryMapper;

	@Resource
	private OrderMapper orderMapper;

	@Resource
	private FeedbackMapper feedbackMapper;

	@Resource
	private BalanceOperationMapper balanceOperationMapper;

	@Resource
	private InvitationMapper invitationMapper;
	
	@Resource
	private FinancingService financingService;
	
	@Resource
	private RepaymentOrderMapper repaymentOrderMapper;

	@Resource(name = "sendSMS")
	private SMSService smsService;

	@Resource(name="executor")
	private AsyncTaskExecutor executor;
	
	@Resource
	private CreditService creditService;

	@Resource
	private ConfigureService configureService;

	@Resource
	private BonusRecordMapper bonusRecordMapper;

	@Resource
	private BankCardMapper bankCardMapper;

	@Resource
	private PopularizeCategoryMapper popularizeCategoryMapper;

	@Resource
	private PopularizeMapper popularizeMapper;

	@Resource
	private ChannelMapper channelMapper;

	@Resource
	private CommonService commonService;

	@Resource
	private MessageService messageService;

	@Resource
	private AccountMapper accountMapper;

	@Resource
	private BalanceAndFinancingService balanceAndFinancingService;
	
	

	@Override
	protected BaseMapper<User> getBaseMapper() {
		return userMapper;
	}
	
	@Override
	public User findUserByMobile(String mobile) {
		UserExample example = new UserExample();
		example.appendCriterion("mobile=", mobile);
		return userMapper.selectOneByExample(example);
	}
	
	


	@Override
	public User findUserByExternal(String external) {
		UserExample example = new UserExample();
		example.appendCriterion("external=", external);
		return userMapper.selectOneByExample(example);
	}

	@Override
	public int findUserCountByMobile(String mobile) {
		UserExample example = new UserExample();
		example.appendCriterion("mobile=", mobile);
		return userMapper.countByExample(example);
	}
	
	
	public String sendIdentifyingCode(final String mobile) {
		return sendIdentifyingCode(mobile, null);
	}

	@SuppressWarnings("unchecked")
	@Override
	public String sendIdentifyingCode(final String mobile, String type) {
		//TODO: 将type重构为枚举类
		if(type == null){
			type = "IDENTIFYING_CODE_TIMEOUT_";
		}
		StringBuilder sb = new StringBuilder();
		Random random = new Random();
		for (int i = 0; i < 4; i++) {
			sb.append(String.valueOf(random.nextInt(10)));
		}

		String identifyingcode = sb.toString();
		logger.info("手机号【" + mobile + "】验证码：" + identifyingcode);
		redisTemplate.opsForValue().set( type + mobile,
				identifyingcode);
		redisTemplate
				.expire(type + mobile, 600, SECONDS);

		SMS sms = new SMS();
		sms.setMobile(mobile);
		sms.setMessage("您本次手机验证码为 " + identifyingcode
				+ " ，请勿将验证码告知他人。如有疑问请致电:400-871-8080");
		sms.setChannel("alauda_verification");
		// if (!"Mac OS X".equals(System.getProperty("os.name"))) {
		smsService.sendSMS(sms);
		// }
		return identifyingcode;
	}

	public String getIdentifyingCode(final String mobile){
		return getIdentifyingCode(mobile,null);
	}
	
	@SuppressWarnings("unchecked")
	@Override
	public String getIdentifyingCode(final String mobile,String type) {
		try {
			final String index ;
			if(type==null){
				index = "IDENTIFYING_CODE_TIMEOUT_";
			}else{
				index = type;
			}
			return (String) redisTemplate
					.execute(new SessionCallback<String>() {
						@SuppressWarnings("rawtypes")
						@Override
						public String execute(RedisOperations operations)
								throws DataAccessException {
							BoundValueOperations<String, String> bvo = operations
									.boundValueOps(index
											+ mobile);
							return bvo.get();
						}
					});
		} catch (Exception e) {
			logger.error("手机验证码出错:" + e.toString());
			return null;
		}
	}

	
	@Override
	@Transactional
	public boolean addUser(User user){
		return addUser(user, null);
	}
	
	@Override
	@Transactional
	public boolean addUser(User user, User inviter) {
		userMapper.insert(user);
		addUserIntegrity(user);
		if (user.getId() != null) {
			user.setExternal(getExternal(user.getId()));
			userMapper.updateByPrimaryKey(user);
		}else
			return false;
		
		//保存推荐人的信息
		if(inviter!=null) {
			User invitee = user;
			if(inviter!=null && invitee!=null && inviter.getId().longValue()!=invitee.getId().longValue()){
				addInvitation(invitee, inviter, Invitation.TYPE_CREDIT);
			}
		}
		logger.info("===================>spring内部事务开始");
		MessageEvent event = new MessageEvent(
				EventConstant.KEY_USER_REGISTER_EVENT, user.getId());
		CommonServiceImpl.applicationContext.publishEvent(event);
		logger.info("===================>spring内部事务结束");
		return registerCredis(user);
	}

	/**
	 * 增加用户数据的完整性
	 * 
	 * @param user
	 * @return
	 */
	private boolean addUserIntegrity(User user) {
		if (user != null && user.getId() != null) {
			if (balanceMapper.selectByPrimaryKey(user.getId()) == null) {
				// 再加入balance
				Balance balance = new Balance();
				balance.setId(user.getId());
				balance.setCreateDate(new Date());
				balance.setModifyDate(new Date());
				balance.setIncome(new BigDecimal(0));
				balance.setAsset(new BigDecimal(0));
				balance.setRedEnvelope(0D);
				// if (Utils.isSendRedEnvelope()) {
				// balance.setRedEnvelope(50D);
				// } else {
				// balance.setRedEnvelope(0D);
				// }
				balanceMapper.insert(balance);
				// if (Utils.isSendRedEnvelope()) {
				// this.addBalanceOperation(50D, user,
				// BalanceOperation.Type.RED_ENVELOPE);
				// }
			}
			if (userInformationMapper.selectByPrimaryKey(user.getId()) == null) {
				// 再加入用户其他信息
				UserInformation userInformation = new UserInformation();
				userInformation.setCreateDate(new Date());
				userInformation.setModifyDate(new Date());
				userInformation.setId(user.getId());
				/*
				 * 加入区域信息
				 */
				String[] regional = RegionalUtil.getCityByMobile(user
						.getMobile());
				if (regional != null && regional.length >= 2) {
					userInformation.setProvince(regional[0]);
					userInformation.setCityname(regional[1]);
				}
				userInformationMapper.insert(userInformation);
			}
			if (creditMapper.selectByPrimaryKey(user.getId()) == null) {
				// 加入积分的操作（注册送多少积分）
				Credit credit = new Credit();
				credit.setCreateDate(new Date());
				credit.setCredits(0);
				credit.setId(user.getId());
				creditMapper.insert(credit);
				// creditService.sendRookieCredits(user,
				// CreditOperation.Operation.REGISTER);
			}
		}
		return true;
	}

	/**
	 * 注册送多少积分
	 * 
	 * @param user
	 * @return
	 */
	private boolean registerCredis(User user) {
		return true;
	}

	@Override
	@Transactional
	public boolean checkUserIntegrity() {
		List<User> list = userMapper.selectByExample(new UserExample(), null);
		if (list != null) {
			for (User user : list) {
				addUserIntegrity(user);
			}
		}
		return false;
	}

	@Override
	public Balance findUserBalance(Long id) {
		return balanceMapper.selectByPrimaryKey(id);
	}

	@Override
	public BigDecimal caculateDayInterestByUserId(Long id) {
		BigDecimal interest = new BigDecimal(0);
		// String now =
		// DateFormatUtils.ISO_DATE_FORMAT.format(Calendar.getInstance());
		// 查询用户名下所有金融包
		FinancingExample financingExample = new FinancingExample();
		financingExample.appendCriterion("user_id=", id);
		List<Financing> financingList = financingMapper.selectByExample(
				financingExample, null);
		if (financingList != null && !financingList.isEmpty()) {
			for (Financing financing : financingList) {
				// 找出当天计算出的利息
				InterestExample interestExample = new InterestExample();
				interestExample.appendCriterion("valueDate<=",
						new java.sql.Date(new Date().getTime()));
				interestExample
						.appendCriterion("date_format(valueDate,\'%Y-%m\')=date_format(now(),\'%Y-%m\')");
				interestExample.appendCriterion("financing_id=",
						financing.getId());
				List<Interest> list = interestMapper.selectByExample(
						interestExample, null);
				if (!isEmpty(list)) {
					for (Interest item : list) {
						if (item.getInterest() != null) {
							interest = interest.add(item.getInterest());
						}
					}
				}
				// Interest nowInterest =
				// interestMapper.selectOneByExample(interestExample);
				// if(nowInterest!=null)
				// interest = interest.add(nowInterest.getInterest());
			}
		}
		return interest;
	}

	@Override
	public boolean addLoginHistory(User user, boolean isSuccess,
			String loginType, String ip, String city, String description) {
		LoginHistory loginHistory = new LoginHistory();
		loginHistory.setUser(user);
		loginHistory.setCreateDate(Calendar.getInstance().getTime());
		loginHistory.setModifyDate(loginHistory.getCreateDate());
		loginHistory.setLoginType(loginType);
		loginHistory.setIp(ip);
		loginHistory.setCity(city);
		loginHistory.setDescription(description);
		return this.loginHistoryMapper.insert(loginHistory) > 0;
	}

	@Override
	public User findUserById(Long id) {
		return this.userMapper.selectByPrimaryKey(id);
	}

	@Override
	public boolean modifyUser(User user) {
		user.setModifyDate(Calendar.getInstance().getTime());

		/*
		 * 更新用户扩展信息
		 */
		UserInformation info = userInformationMapper.selectByPrimaryKey(user
				.getId());
		if (info.getCitycode() == null && user.getIdCard() != null) {
			info.setBirth(IdcardUtils.getBirthByIdCard(user.getIdCard()));
			info.setGender(IdcardUtils.getGenderByIdCard(user.getIdCard()));
			info.setCitycode(IdcardUtils.getCitycodeByIdCard(user.getIdCard()));
			if (info.getProvince() == null) {
				info.setProvince(IdcardUtils.getProvinceByIdCard(user
						.getIdCard()));
			}
			userInformationMapper.updateByPrimaryKey(info);
		}
		return this.userMapper.updateByPrimaryKey(user) > 0;
	}

	@Override
	public User findUserByUserKey(String userKey) {
		UserExample example = new UserExample();
		example.appendCriterion("userKey=", userKey);
		return userMapper.selectOneByExample(example);
	}

	@Override
	public Pager<Map<String, Object>> findFinancingByUserId(User user,
			Pager<Map<String, Object>> pager, String statusStr) {
		Map<String, Object> params = new HashMap<String, Object>();
		params.put("user_id", user.getId());
		params.put("startNumber", pager.getStartNumber());
		params.put("pageSize", pager.getPageSize());
		params.put("statusStr", statusStr);
		pager.setList(financingMapper.findByUserId(params));
		pager.setTotalCount(financingMapper.findCountByUserId(params));
		if (!isEmpty(pager.getList())) {
			for (Map<String, Object> item : pager.getList()) {
				Date expiredDate = addDays((Date) item.get("settlementDate"),
						-1);
				Financing.Status status = Financing.Status
						.valueOf((String) item.get("status"));
				item.put("statusStr",
						Financing.getStatusStr(expiredDate, status));
			}
		}
		return pager;
	}

	@Override
	public Double findTotalAmountByUserId(User user) {
		Double investment = financingMapper.findTotalAmountByUserId(user
				.getId());
		return investment == null ? 0 : investment;
	}

	@Override
	public User resetUserPassword(long id) {

		User user = this.findUserById(id);
		String newPassword = genareatePassword();
		user.setPassword(Encryption.encrypt(newPassword));
		userMapper.updateByPrimaryKey(user);

		SMS sms = new SMS();
		sms.setMobile(user.getMobile());
		sms.setMessage("您的登陆密码已经重置，新密码：" + newPassword);
		sms.setChannel("builtin_notice");
		smsService.sendSMS(sms);

		return user;
	}

	/**
	 * 生成随机密码
	 * 
	 * @return 随机密码
	 */
	private String genareatePassword() {
		String password = "";
		Random random = new Random();
		for (int i = 0; i < 6; i++) {
			password += String.valueOf(random.nextInt(9));
		}
		return password;
	}

	@Override
	public boolean saveFeedback(Feedback feedback) {
		feedback.setCreateDate(new Date());
		feedback.setModifyDate(new Date());
		return feedbackMapper.insert(feedback) > 0;
	}

	@Transactional
	@Override
	public boolean addBalanceOperation(Double amount, User user,
			BalanceOperation.Type type) {
		// 查询用户的资金账户
		Balance balance = this.balanceMapper.findBalanceByUserId(user);
		if (amount == null)
			amount = 0D;
		balance.setRedEnvelope(balance.getRedEnvelope() + amount);// 设置最新数量的红包
		balance.setModifyDate(RateUtil.getDate());// 设置修改日期

		// 增加资金账户变动记录
		BalanceOperation balanceOperation = new BalanceOperation();
		balanceOperation.setCreateDate(RateUtil.getDate());
		balanceOperation.setModifyDate(balanceOperation.getCreateDate());
		balanceOperation.setBalance(balance);
		balanceOperation.setAmount(new BigDecimal(String.valueOf(amount)));
		balanceOperation.setType(type);// 类型设置成获得红包
		balanceOperationMapper.insert(balanceOperation);

		return this.balanceMapper.updateByPrimaryKey(balance) > 0;
	}

	@Override
	public User findUserByOpenId(String openid) {
		UserExample example = new UserExample();
		example.appendCriterion("openId=", openid);
		return userMapper.selectOneByExample(example);
	}

	@Override
	public void sendSuccessMessage(Financing financing) {
		User user = this.userMapper.selectByPrimaryKey(financing.getUser()
				.getId());
		StringBuilder sb = new StringBuilder();
		sb.append("尊敬的");
		sb.append(user.getRealName());
		sb.append("，您已成功购买");
		sb.append((int) financing.getAmount().doubleValue());
		sb.append("元[");
		sb.append(financing.getProduct().getName());
		sb.append("]，期限");
		sb.append(financing.getProduct().getTerm());
		sb.append("天，预期年化");
		sb.append(financing.getProduct().getFinalRate()
				.multiply(new BigDecimal(100))
				.setScale(1, RoundingMode.HALF_DOWN));
		sb.append("%，感谢您的信任。客服热线:400-871-8080");
		String text = sb.toString();
		logger.info(String.format(
				"======================>手机号码为[%s]的用户发送成功短信[%s]",
				user.getMobile(), text));
		final SMS sms = new SMS();
		sms.setMobile(user.getMobile());
		sms.setMessage(text);
		sms.setChannel("alauda_order");
		if (!"Mac OS X".equals(System.getProperty("os.name"))) {
			executor.execute(new Runnable() {
				@Override
				public void run() {
					smsService.sendSMS(sms);
				}
			});
		}
	}

	public void sendInvitationMessage(Financing financing) {
		Date nowDate = new Date();
		/**
		 * 查询是否有邀请送积分活动来源的邀请信息
		 */
		Invitation invitation =getInvitation(financing.getUser());
		if (invitation != null) {

			JSONObject invite_config = new JSONObject(
					configureService.getActivityConfig("INVITE_CONFIG"));
			JSONArray levels = invite_config.getJSONObject("config")
					.getJSONArray("levels");
			
			//int number = levels.getJSONObject(
			//		this.balanceAndFinancingService.checkClassify(invitation
			//				.getInviter())).getIntValue("bonus");
			SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");
			int number = 50;
			Date now = new Date();
			try {
				if(now.after(formatter.parse("2016-12-06")) && now.before(formatter.parse("2016-12-20")))
					number = 100;
			} catch (ParseException e1) {
				
			}
			
			
			try {
				BonusRecord record = new BonusRecord();
				record.setAmount(new BigDecimal(number));
				record.setExpiredDate(addDays(nowDate, 90));
				record.setDescription("您邀请的好友["
						+ invitation.getInvitee().getMobile() + "]首次交易，平台赠送给您"
						+ number + "元奖励红包，再接再厉哦~");
				record.setType("INVITATION_INVITER");
				record.setCode("INVITATION_INVITER");
				record.setConsume(false);
				record.setUser(invitation.getInviter());
				record.setRemaining(record.getAmount());
				record.setCreateDate(nowDate);
				record.setModifyDate(nowDate);
				record.setRelated("" + invitation.getInvitee().getId());
				bonusRecordMapper.insert(record);

				invitation
						.setAmount(invitation.getAmount() == null ? new Double(
								number)
								: (invitation.getAmount().intValue() + number));
				invitationMapper.updateByPrimaryKey(invitation);
			} catch (Exception e) {
				e.printStackTrace();
			}
			
		}
		
	}

	@Override
	public User findUserByIdCard(String idCard, Long id) {
		UserExample example = new UserExample();
		example.appendCriterion("idCard=", idCard);
		example.appendCriterion("id<>", id);
		return userMapper.selectOneByExample(example);
	}

	@Override
	public Pager<User> findUsersByKeyword(String keyword, Pager<User> pager) {

		// 查询条件
		UserExample example = new UserExample();
		if (keyword != null && !keyword.equals("")) {
			example.appendCriterion("realName =", keyword.trim());

			Criteria mobile = example.createCriteria();
			mobile.addCriterion("mobile =", keyword.trim());
			example.or(mobile);

			Criteria idCard = example.createCriteria();
			idCard.addCriterion("idCard =", keyword.trim());
			example.or(idCard);

			Criteria external = example.createCriteria();
			external.addCriterion("external =", keyword.trim());
			example.or(external);
		}
		example.setOrderByClause("createDate desc");

		pager.setList(userMapper.selectByExample(example, pager));
		pager.setTotalCount(userMapper.countByExample(example));
		return pager;
	}

	// @Override
	// public void sendSuccessMessage(String mobile) {
	// SMS sms = new SMS();
	// sms.setMobile(mobile);
	// sms.setMessage("您本次手机验证码为"+identifyingcode + "，请勿将验证码告知他人。");
	// sms.setChannel("alauda_verification");
	// smsService.sendSMS(sms);
	// }

	@Override
	public List<User> findUsersByRealNameWithLike(String realName,
			Pager<User> pager) {
		UserExample example = new UserExample();
		example.appendCriterion("realName like  ", "%" + realName + "%");
		return userMapper.selectByExample(example, pager);
	}

	@Override
	public User findUserByExample(UserExample example) {
		return this.userMapper.selectOneByExample(example);
	}

	@Override
	@Transactional
	public void updateUsersExternal() {
		List<User> list = userMapper.findAllUsers();
		if (!isEmpty(list)) {
			for (User user : list) {
				userMapper.updateUserExternal(getExternal(user.getId()),
						user.getId());
			}
		}
	}

	@Override
	public boolean saveInvitation(Invitation entity) {
		if (entity.getId() == null)
			return invitationMapper.insert(entity) > 0;
		return invitationMapper.updateByPrimaryKey(entity) > 0;
	}

	@Transactional
	@Override
	public boolean addInvitation(User invitee, User inviter, Integer type) {
		Invitation invitation = new Invitation();
		invitation.setCreateDate(new Date());
		invitation.setModifyDate(invitation.getCreateDate());
		invitation.setInvitee(invitee);
		invitation.setInviter(inviter);
		invitation.setType(type);
		User ancestor = inviter;
		StringBuilder sb = new StringBuilder(">" + ancestor.getId() + ">");
		for (int i = 0; i < MAX_VALUE; i++) {
			InvitationExample example = new InvitationExample();
			example.appendCriterion("invitee_id<>inviter_id");
			example.appendCriterion("invitee_id=", ancestor.getId());
			Invitation in2 = invitationMapper.selectOneByExample(example);
			if (in2 != null) {
				ancestor = in2.getInviter();
				sb.insert(0, ">" + ancestor.getId());
			} else {
				break;
			}
		}
		invitation.setAncestor(sb.toString());
		return saveInvitation(invitation);
	}

	@Override
	public List<Invitation> findInvitationByUser(User user) {
		List<Invitation> invitations = invitationMapper
				.findInvitationByUser(user);
		if (!isEmpty(invitations)) {
			for (Invitation invitation : invitations) {
				invitation.setCount(invitationMapper
						.countFinancingByUser(invitation.getInvitee()));
			}
		}
		return invitations;
	}

	@Override
	public Invitation findInvitation1(User user) {
		return invitationMapper.findInvitationByInvitee(user);
	}

	@Override
	public void sendMessageAfterRegister(String mobile) {
		SMS sms = new SMS();
		sms.setMobile(mobile);
		sms.setMessage("感谢注册“快聚财”，您可以在苹果、安卓的应用商店下载安装“快聚财”客户端，或通过“快聚财”官方微信公众号实时关注我们。");
		sms.setChannel("alauda_register");
		if (!"Mac OS X".equals(System.getProperty("os.name"))) {
			smsService.sendSMS(sms);
		}
	}

	@Override
	public UserInformation findUserInformationById(Long id) {
		return userInformationMapper.selectByPrimaryKey(id);
	}

	@Override
	public List<Invitation> findInvitationByExample(InvitationExample example,
			Pager<Invitation> pager) {
		return this.invitationMapper.selectByExample(example, pager);
	}

	@Override
	public int findInvitationCountByExample(InvitationExample example) {
		return this.invitationMapper.countByExample(example);
	}

	@Override
	public int updateFinancialIncome() {
		InvitationExample example = new InvitationExample();
		example.appendCriterion("type=", Invitation.TYPE_ANNUAL_MEETING_2015);
		List<Invitation> list = invitationMapper.selectByExample(example, null);
		if (!isEmpty(list)) {
			for (Invitation invitation : list) {
				int interval = RateUtil.calculateDate(invitation
						.getCreateDate(), Calendar.getInstance().getTime());
				int term = interval > invitation.getTerm() ? invitation
						.getTerm() : interval;
				logger.info("==========================>term1=" + term);
				// if(term>invitation.getTerm()){
				// term = invitation.getTerm();
				// }
				logger.info("==========================>term2=" + term);
				BigDecimal interest = new BigDecimal(invitation.getAmount()
						.doubleValue()
						* (invitation.getInterestRate().doubleValue())
						/ 360
						* term).setScale(2, RoundingMode.UP);
				invitation.setIncome(interest.doubleValue());
				invitationMapper.updateByPrimaryKey(invitation);
				logger.info("==========================>interest=" + interest);
				if (interval >= invitation.getTerm()) {
					MessageEvent event = new MessageEvent(
							EventConstant.KEY_ANNUAL_MEETING_2015_INCOME,
							invitation);
					CommonServiceImpl.applicationContext.publishEvent(event);
				}
			}
		}
		return 0;
	}

	@Override
	public int updateFinancialExpired(Map<String, Object> params) {
		return invitationMapper.updateFinancialExpired(params);
	}

	@Override
	public int updateInvitationById(Invitation invitation) {
		return invitationMapper.updateByPrimaryKey(invitation);
	}

	@Override
	public int updateBalanceCash() {
		return this.balanceMapper.updateCashById(null, null);
	}

	@Override
	public int updateBalanceCashed(Double cash, User user) {
		return this.balanceMapper.updateCashedById(cash, user.getId());
	}

	@Override
	public Credit findCreditById(Long id) {
		return this.creditMapper.selectByPrimaryKey(id);
	}

	@Override
	public int findUserCountByIp(String ip) {
		UserExample example = new UserExample();
		example.appendCriterion("ip=", trimToEmpty(ip));
		example.appendCriterion("DATE_FORMAT(`createDate`, \'%Y-%m-%d\')=",
				ISO_DATE_FORMAT.format(new Date()));
		return userMapper.countByExample(example);
	}

	@Override
	public int updateUserInformation(UserInformation userInformation) {
		return userInformationMapper.updateByPrimaryKey(userInformation);
	}

	@Override
	public void changeMobile(Long userId, String newMobile)
			throws BusinessException {

		if (!Mobile.isValid(newMobile)) {
			throw new BusinessException("无效手机号");
		}

		UserExample example = new UserExample();
		example.appendCriterion("mobile =", newMobile);
		Pager<User> pager = new Pager<>();
		List<User> users = this.userMapper.selectByExample(example, pager);
		if (users.size() > 0) {
			User newUser = users.get(0);
			checkUserAcountIsUsed(newUser);

			// 对换手机号码
			User user = this.userMapper.selectByPrimaryKey(userId);
			String mobile = user.getMobile();

			newUser.setMobile("");
			newUser.setModifyDate(new Date());
			this.userMapper.updateByPrimaryKey(newUser);

			user.setMobile(newMobile);
			user.setModifyDate(new Date());
			this.userMapper.updateByPrimaryKey(user);

			newUser.setMobile(mobile);
			newUser.setModifyDate(new Date());
			this.userMapper.updateByPrimaryKey(newUser);
		} else {
			User user = this.userMapper.selectByPrimaryKey(userId);
			user.setMobile(newMobile);
			user.setModifyDate(new Date());
			this.userMapper.updateByPrimaryKey(user);
		}
	}

	/**
	 * 检查用户账号是否已使用
	 * 
	 * @param user
	 *            用户
	 * @throws BusinessException
	 */
	private void checkUserAcountIsUsed(User user) throws BusinessException {

		// 实名认证
		if (StringUtils.isNotBlank((user.getRealName()))) {
			throw new BusinessException("用户已实名认证");
		}

		// 订单记录
		OrderExample orderExample = new OrderExample();
		orderExample.appendCriterion("user_id =", user.getId());
		orderExample.appendCriterion("status !=", "STATUS_OVERDUE");
		if (this.orderMapper.countByExample(orderExample) > 0) {
			throw new BusinessException("用户已有订单记录");
		}

		// 绑卡记录
		BankCardExample bankCardExample = new BankCardExample();
		bankCardExample.appendCriterion("user_id =", user.getId());
		bankCardExample.appendCriterion("status =", "BINDED");
		if (this.bankCardMapper.countByExample(bankCardExample) > 0) {
			throw new BusinessException("用户已有绑卡记录");
		}
	}

	@Override
	public void sendUniversalMessage(final String mobile, final String text,
			final String channel) {

		Runnable task = new Runnable() {
			@Override
			public void run() {
				try {
					logger.info("=====================>短信发送:" + mobile + "，内容："
							+ text);
					SMS sms = new SMS();
					sms.setMobile(mobile);
					sms.setMessage(text);
					sms.setChannel(channel);
					smsService.sendSMS(sms);
				} catch (Exception e) {
					e.printStackTrace();
				}

			}
		};

		if (CommonServiceImpl.applicationContext == null) {
			new Thread(task).start();
		} else {
			Executor executor = (Executor) CommonServiceImpl.applicationContext
					.getBean("executor");
			executor.execute(task);
		}
	}

	@Override
	public List<User> findAllUsers() {
		return this.userMapper.findAllUsers();
	}

	@Override
	public List<UserInformation> findUserInformationsByIds(
			List<Long> userInformationIds) {

		if (userInformationIds == null || userInformationIds.size() < 1) {
			return new ArrayList<UserInformation>();
		}

		Pager<UserInformation> pager = new Pager<UserInformation>();
		pager.setPageSize(10000);

		UserInformationExample example = new UserInformationExample();
		String condition = "id in(%s)";
		String ids = "";
		for (Long userInformationId : userInformationIds) {
			ids += userInformationId + ",";
		}
		ids = ids.substring(0, ids.length() - 1);
		example.appendCriterion(String.format(condition, ids));

		return this.userInformationMapper.selectByExample(example, pager);
	}

	@Override
	public String findRefereeNameByReferee(String referee) {

		if (referee.startsWith("P:")) {
			return findPopularizeName(referee);
		} else {
			Channel channel = findChannelByNumber(referee);
			if (channel == null) {
				return "";
			} else {
				return channel.getName();
			}
		}
	}

	private Channel findChannelByNumber(String number) {

		ChannelExample example = new ChannelExample();
		example.appendCriterion("number =", number);
		return this.channelMapper.selectOneByExample(example);
	}

	/**
	 * 查找推广名称
	 * 
	 * @param number
	 * @return
	 */
	private String findPopularizeName(String number) {

		String name = "";

		String sourceId = number.replace("P:", "");
		String[] items = sourceId.split("-");

		if (items.length == 1) {
			Long biggerId = Long.parseLong(items[0]);
			PopularizeCategory bigger = this.popularizeCategoryMapper
					.selectByPrimaryKey(biggerId);
			name = bigger.getName();
		} else if (items.length == 2) {
			Long categoryId = Long.parseLong(items[1]);
			PopularizeCategory category = this.popularizeCategoryMapper
					.selectByPrimaryKey(categoryId);
			name = category.getName();
		} else if (items.length == 3) {
			Long popularizeId = Long.parseLong(items[2]);
			Popularize popularize = this.popularizeMapper
					.selectByPrimaryKey(popularizeId);
			name = popularize.getName();
		}

		return name;
	}

	@Override
	public List<BankCard> getBankCardsByUserId(Long id) {
		return bankCardMapper.getBankCardsByUserid(id);
	}

	@Override
	public Invitation getInvitee(Long id) {

		InvitationExample example = new InvitationExample();
		example.appendCriterion("invitee_id=", id);
		return invitationMapper.selectOneByExample(example);
	}

	@Override
	public Pager<Invitation> findInvintation(String keyword,
			Pager<Invitation> pager) {

		Map<String, Object> map = new HashMap<String, Object>();

		if (StringUtil.isNotBlank(keyword)) {
			map.put("keyword", keyword);
		}

		map.put("startNumber", pager.getStartNumber());
		map.put("pageSize", pager.getPageSize());

		pager.setList(this.invitationMapper.selectInvitations(map));
		pager.setTotalCount(this.invitationMapper.selectInvitationsCount(map));

		return pager;
	}

	@Override
	public Account findAccountByExample(AccountExample example) {
		return accountMapper.selectOneByExample(example);
	}

	@Override
	@Transactional
	public int insertAccount(Account account) {
		return accountMapper.insert(account);
	}

	@Override
	@Transactional
	public int updateAccount(Account account) {
		return accountMapper.updateByPrimaryKey(account);
	}

	@Override
	public List<Long> findUserIdsByBirthday(Date birthday) {
		String day = DateFormatUtils.format(birthday, "MMdd");
		day = "__________" + day + "____";
		return this.userInformationMapper.findUserIdsByBirthday(day);
	}

	@Override
	public Pager<Financing> findSleepingUsers(Integer keyword,
			Pager<Financing> pager) {

		Map<String, Object> map = new HashMap<String, Object>();

		map.put("keyword", keyword);
		map.put("startNumber", pager.getStartNumber());
		map.put("pageSize", pager.getPageSize());

		pager.setList(this.financingMapper.selectSleepingUsers(map));
		pager.setTotalCount(this.financingMapper.selectSleepingUsersCount(map));

		return pager;

	}

	@Override
	public Pager<User> findNewUsers(Integer keyword, Pager<User> pager) {
		Map<String, Object> map = new HashMap<String, Object>();

		map.put("keyword", keyword);
		map.put("startNumber", pager.getStartNumber());
		map.put("pageSize", pager.getPageSize());

		pager.setList(this.userMapper.selectNewUsers(map));
		pager.setTotalCount(this.userMapper.selectNewUsersCount(map));

		return pager;
	}

	@Override
	public Pager<User> findFollowSleepingUsers(String keyword, String status,
			String account, String followDate, Pager<User> pager) {
		Map<String, Object> map = new HashMap<String, Object>();

		if (StringUtil.isNotBlank(keyword)) {
			map.put("keyword", keyword);
		}
		if (StringUtil.isNotBlank(status)) {
			map.put("status", status);
		}
		if (StringUtil.isNotBlank(account)) {
			map.put("account", account);
		}
		if (StringUtil.isNotBlank(followDate)) {
			map.put("followDate", followDate);
		}

		map.put("startNumber", pager.getStartNumber());
		map.put("pageSize", pager.getPageSize());

		pager.setList(this.userMapper.selectFollowSleepingUsers(map));
		pager.setTotalCount(this.userMapper.selectFollowSleepingUsersCount(map));

		return pager;
	}

	@Override
	public Invitation getInvitation(User user) {
		InvitationExample invitationExample = new InvitationExample();
		invitationExample.appendCriterion("type=", Invitation.TYPE_CREDIT);
		invitationExample.appendCriterion("invitee_id<>inviter_id");
		invitationExample.appendCriterion("invitee_id=", user.getId());
		Invitation invitation = invitationMapper
				.selectOneByExample(invitationExample);
		
		if(invitation == null)
			 return null;
		else
			 return invitation;
		
	}

	/**
	 * 
	 * 判断是否是新手
	 * 
	 * 如果有有效的资产则不是新手
	 * @param user
	 * 
	 */
	@Override
	public Boolean isRookie(User user) {
			
		return balanceAndFinancingService.findLatestFinancingByUser(user) == null;
		
	}
	
	@Override
	public BigDecimal getYesterdayIncome(User user){
		
		BigDecimal yesterdayIncome = new BigDecimal(0);
		Calendar cal = Calendar.getInstance();
		cal.add(Calendar.DATE, -1);
		String yesterday = new SimpleDateFormat("yyyy-MM-dd").format(cal.getTime());
		List<Interest> interestList = financingService.findInterestByUser(user, yesterday);

		for(Interest i : interestList){
				yesterdayIncome = yesterdayIncome.add(i.getInterest());
		}
		
		return yesterdayIncome;
		
	}
	
	
	@Override
	public BigDecimal getUnpayIncome(User user){
		FinancingExample example = new FinancingExample();
		example.appendCriterion("user_id=", user.getId());
		example.appendCriterion("status=", "STATUS_INTEREST");
		List<Financing> list = financingMapper.selectByExample(example, null);
		BigDecimal unpayIncome = new BigDecimal(0);
		for(Financing f : list)
			unpayIncome = unpayIncome.add(f.getIncome());
		return unpayIncome;
		
	}
	
	@Override
	public BigDecimal getUnpayAmount(User user){
		FinancingExample example = new FinancingExample();
		example.appendCriterion("user_id=", user.getId());
		example.appendCriterion("`status`<>", Financing.Status.STATUS_PAYBACK);
		example.appendCriterion("`status`<>", Financing.Status.STATUS_REPAID);
		List<Financing> list = financingMapper.selectByExample(example, null);
		BigDecimal unpayIncome = new BigDecimal(0);
		for(Financing f : list)
			unpayIncome = unpayIncome.add(f.getAmount());
		return unpayIncome;
		
	}

	@Override
	public Date theFirstTimeToBuy(User user) {
		FinancingExample example = new FinancingExample();
		example.appendCriterion("user_id=", user.getId());
		example.setOrderByClause(" createDate ASC ");
		Financing f = financingMapper.selectOneByExample(example);
		if(f == null)
			return null;
		return f.getCreateDate();
	}

	@Override
	public Date theFirstTimeToRepay(User user) {
		FinancingExample example = new FinancingExample();
		example.appendCriterion("user_id=", user.getId());
		example.appendCriterion(" repaymentTime is NOT NULL ");
		example.setOrderByClause(" repaymentTime ASC ");
		Financing f = financingMapper.selectOneByExample(example);
		if( f == null)
			 return null;
		return f.getRepaymentTime();
	}

	@Override
	public BigDecimal totalIncome(User user, Date beginDate, Date endDate) {
		FinancingExample example = new FinancingExample();
		example.appendCriterion("user_id=", user.getId());
		if(beginDate!=null)
			example.appendCriterion("createDate>", beginDate);
		
		if(endDate!=null)
			example.appendCriterion("createDate<", endDate);
		
		BigDecimal totalIncome = new BigDecimal(financingMapper.sumByExample("income", example)).setScale(2, BigDecimal.ROUND_HALF_UP);
		
		RepaymentOrderExample rexample = new RepaymentOrderExample();
		rexample.appendCriterion("userId=", user.getId());
		rexample.appendCriterion("`financingIds`  is null");
		Double bouns = repaymentOrderMapper.sumByExample("amount", rexample);
		totalIncome = totalIncome.add(new BigDecimal(bouns));
		return totalIncome;
	}

	@Override
	public int countUserIncomeMoreThan(BigDecimal amount){
		return userMapper.countUserIncomeMoreThan(amount);
	}
	

}
